package com.ddwl.wallet.service;

import com.ddwl.common.constant.BaseEnum;
import com.ddwl.common.exception.CommonException;
import com.ddwl.common.exception.ExceptionCode;
import com.ddwl.common.exception.ParamException;
import com.ddwl.common.feign.api.GoodsApi;
import com.ddwl.common.feign.api.ShopApi;
import com.ddwl.common.util.BeanConverUtils;
import com.ddwl.common.util.ObjectUtil;
import com.ddwl.schema.bo.base.PageBo;
import com.ddwl.schema.bo.wallet.CouponBo;
import com.ddwl.schema.vo.base.PageVo;
import com.ddwl.schema.vo.goods.ItemVo;
import com.ddwl.schema.vo.shop.ShopVo;
import com.ddwl.schema.vo.wallet.CouponVo;
import com.ddwl.wallet.dao.model.Coupon;
import com.ddwl.wallet.repository.CouponRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.Instant;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author hemiaojun
 * @Date 2021/9/7 17:12
 */
@Service
@RequiredArgsConstructor
public class CouponService {

    private final CouponRepository couponRepository;
    private final ShopApi shopApi;
    private final GoodsApi goodsApi;

    public CouponVo info(String couponId) {
        Coupon coupon = couponRepository.findById(couponId).orElse(null);
        ParamException.isNull(coupon);
        Map<String, ShopVo> shopMap;
        Map<String, ItemVo> itemMap;
        if (!CollectionUtils.isEmpty(coupon.getShopIds())) {
            List<ShopVo> shops = shopApi.getShopListByIds(coupon.getShopIds()).getResult();
            shopMap = shops.stream().collect(Collectors.toMap(ShopVo::getId, Function.identity()));
        } else {
            shopMap = new HashMap<>(0);
        }
        if (StringUtils.hasText(coupon.getItemId())) {
            List<ItemVo> items = goodsApi.queryItems(Collections.singleton(coupon.getItemId())).getResult();
            itemMap = items.stream().collect(Collectors.toMap(ItemVo::getId, Function.identity()));
        } else {
            itemMap = new HashMap<>(0);
        }
        CouponVo vo = BeanConverUtils.convertBean(coupon, CouponVo.class);
        if (!CollectionUtils.isEmpty(coupon.getShopIds())) {
            vo.setShops(coupon.getShopIds().stream().map(shopId -> shopMap.get(shopId)).collect(Collectors.toList()));
        }
        if (StringUtils.hasText(coupon.getItemId())) {
            vo.setItem(itemMap.get(coupon.getItemId()));
        }
        return vo;
    }

    public void create(CouponBo bo) {
        Coupon coupon = BeanConverUtils.convertBean(bo, Coupon.class);
        coupon.setDflag(BaseEnum.DflagEnum.NOT_DELETE.getCode());
        coupon.setGmtCreated(Instant.now());
        couponRepository.save(coupon);
    }

    public void update(CouponBo bo) {
        Coupon coupon = couponRepository.findById(bo.getId()).orElse(null);
        if (coupon == null) {
            throw new CommonException(ExceptionCode.DATA_NOT_EXISTS);
        }
        BeanUtils.copyProperties(bo, coupon, ObjectUtil.getNullFields(bo));
        coupon.setGmtModified(Instant.now());
        couponRepository.save(coupon);
    }

    public PageVo<CouponVo> page(PageBo<CouponBo> pageBo) {
        Coupon coupon = new Coupon();
        coupon.setDflag(BaseEnum.DflagEnum.NOT_DELETE.getCode());
        if (pageBo.getParam() != null) {
            BeanUtils.copyProperties(pageBo.getParam(), coupon);
        }
        Example<Coupon> example = Example.of(coupon, ExampleMatcher.matching());
        Page<Coupon> pageable = couponRepository.findAll(example, PageRequest.of(pageBo.getPage() - 1, pageBo.getPageSize(), Sort.by(Sort.Direction.DESC, "gmtCreated")));
        PageVo<CouponVo> pageVo = new PageVo<>();
        pageVo.setTotal(pageable.getTotalElements());
        List<Coupon> coupons = pageable.getContent();
        if (CollectionUtils.isEmpty(coupons)) {
            pageVo.setData(new ArrayList<>());
            return pageVo;
        }
        Set<String> shopIds = new HashSet<>();
        Set<String> itemIds = new HashSet<>();
        coupons.forEach(entity -> {
            if (!CollectionUtils.isEmpty(entity.getShopIds())) {
                shopIds.addAll(entity.getShopIds());
            }
            if (entity.getItemId() != null) {
                itemIds.add(entity.getItemId());
            }
        });
        Map<String, ShopVo> shopMap;
        Map<String, ItemVo> itemMap;
        if (!CollectionUtils.isEmpty(shopIds)) {
            List<ShopVo> shops = shopApi.getShopListByIds(shopIds).getResult();
            shopMap = shops.stream().collect(Collectors.toMap(ShopVo::getId, Function.identity()));
        } else {
            shopMap = new HashMap<>(0);
        }
        if (!CollectionUtils.isEmpty(itemIds)) {
            List<ItemVo> items = goodsApi.queryItems(itemIds).getResult();
            itemMap = items.stream().collect(Collectors.toMap(ItemVo::getId, Function.identity()));
        } else {
            itemMap = new HashMap<>(0);
        }
        pageVo.setData(coupons.stream().map(entity -> {
            CouponVo vo = BeanConverUtils.convertBean(entity, CouponVo.class);
            if (!CollectionUtils.isEmpty(entity.getShopIds())) {
                vo.setShops(entity.getShopIds().stream().map(shopId -> shopMap.get(shopId)).collect(Collectors.toList()));
            }
            if (StringUtils.hasText(entity.getItemId())) {
                vo.setItem(itemMap.get(entity.getItemId()));
            }
            return vo;
        }).collect(Collectors.toList()));
        return pageVo;
    }


    public List<CouponVo> shop(String shopId) {
        List<Coupon> coupons = couponRepository.findByShopId(shopId);
        Set<String> itemIds = new HashSet<>();
        coupons.forEach(entity -> {
            if (entity.getItemId() != null) {
                itemIds.add(entity.getItemId());
            }
        });
        Map<String, ItemVo> itemMap;

        if (!CollectionUtils.isEmpty(itemIds)) {
            List<ItemVo> items = goodsApi.queryItems(itemIds).getResult();
            itemMap = items.stream().collect(Collectors.toMap(ItemVo::getId, Function.identity()));
        } else {
            itemMap = new HashMap<>(0);
        }
        return coupons.stream().map(entity -> {
            CouponVo vo = BeanConverUtils.convertBean(entity, CouponVo.class);
            if (StringUtils.hasText(entity.getItemId())) {
                vo.setItem(itemMap.get(entity.getItemId()));
            }
            return vo;
        }).collect(Collectors.toList());
    }

    public void delete(CouponBo bo) {
        Coupon coupon = couponRepository.findById(bo.getId()).orElse(null);
        if (coupon == null) {
            throw new CommonException(ExceptionCode.DATA_NOT_EXISTS);
        }
        coupon.setDflag(BaseEnum.DflagEnum.DELETED.getCode());
        coupon.setGmtModified(Instant.now());
        couponRepository.save(coupon);
    }


}
